package org.dallasrowing.logbook.ui.view;

import java.util.List;

import org.dallasrowing.logbook.Config;
import org.dallasrowing.logbook.Version;
import org.dallasrowing.logbook.util.FormatUtil;
import org.dallasrowing.model.LogBookEntry;
import org.dallasrowing.model.Rower;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;


public class SWTMainWindow implements LogBookWindow {

	private final String[] tableTitles = {"Start", "End", "Name(s)", "Level(s)", "Shell used", "mi rowed/m erged", "Remarks"};
	
	private Display display = null;
	private Shell sShell = null;
	private Table currentEntriesTable;
	private Button signInButton;
	private Button reportDamageButton;
	private Button signOutButton;  
	private Button reportsButton;

	private Button adminButton;

	
	public SWTMainWindow()
	{
		createMainWindow();
		sShell.setMaximized(true);
	}

	public void openWindow()
	{
		sShell.open();
		while (!sShell.isDisposed())
		{
			if (!display.readAndDispatch())
			{
				display.sleep();
			}
		}
		display.dispose();
	}

	
	/**
	 * This method initializes sShell
	 */
	private void createMainWindow() {
		display = new Display();
		sShell = new Shell(display);
		sShell.setSize(new Point(800, 600));
		sShell.setText("Dallas Rowing Club - Logbook [VERSION: " + new Version().buildNumber + "]");
		sShell.setLayout(new GridLayout(1,false));
		sShell.setImage(new Image(display, getClass().getResourceAsStream("/drclogo.bmp")));

		GridData gridData = new GridData( GridData.FILL_HORIZONTAL);
		createButtons(sShell).setLayoutData( gridData );

		gridData = new GridData( GridData.FILL_BOTH);
		createCurrentEntriesTable(sShell).setLayoutData( gridData );
		
		sShell.setDefaultButton(signInButton);
		preventIconified(sShell);
	}

	private void preventIconified(final Shell shell) {
		shell.addShellListener(new ShellAdapter() {
			public void shellIconified(ShellEvent e) {
				sShell.setMaximized(true);
			}
		});
	}

	private Composite createCurrentEntriesTable(Composite parent) {
		Group main = new Group(parent, SWT.BORDER);
		main.setText("Current Entries");
		TableColumnLayout tableColumnLayout = new TableColumnLayout();
		main.setLayout(tableColumnLayout);
		
		currentEntriesTable = new Table (main,  SWT.FULL_SELECTION | SWT.VIRTUAL);
		currentEntriesTable.setLinesVisible (true);
		currentEntriesTable.setHeaderVisible (true);

		Integer[] weights = Config.getColumnWidths();
		for (int i=0; i<tableTitles.length; i++) {
			TableColumn column = new TableColumn (currentEntriesTable, SWT.NONE);
			column.setText (tableTitles [i]);
			tableColumnLayout.setColumnData(column, new ColumnWeightData(weights[i]));
		}	

		return main;
	}

	/**
	 * This method initializes tabFolder	
	 *
	 */
	private Composite createButtons(Composite parent) {
		Group main = new Group(parent, SWT.NONE);
		main.setText("Actions");
		GridLayout gridLayout = new GridLayout(3, false);
		gridLayout.marginWidth = 50;
		gridLayout.marginHeight = 10;
		gridLayout.horizontalSpacing = 10;
		gridLayout.verticalSpacing = 10;
		main.setLayout( gridLayout );

		GridData gridData = null;
		
		gridData = new GridData( GridData.FILL_BOTH);
		gridData.verticalSpan=3;
		Image drcLogo = new Image(display, getClass().getResourceAsStream("/drclogo-big.bmp"));
		Label logo = new Label(main, SWT.NONE);
		logo.setImage(drcLogo);
		logo.setLayoutData(gridData);
	
		signInButton = new Button( main, SWT.PUSH);
		gridData = new GridData( GridData.FILL_HORIZONTAL);
		signInButton.setLayoutData( gridData );
		signInButton.setText("Sign In...");
		
		reportDamageButton = new Button( main, SWT.PUSH);
		gridData = new GridData( GridData.FILL_HORIZONTAL);
		reportDamageButton.setLayoutData( gridData );
		reportDamageButton.setText("Report Damage...");
		reportDamageButton.setEnabled(true);
		
		signOutButton = new Button( main, SWT.PUSH);
		gridData = new GridData( GridData.FILL_HORIZONTAL);
		signOutButton.setLayoutData( gridData );
		signOutButton.setText("Sign Out...");
		
		reportsButton = new Button( main, SWT.PUSH);
		gridData = new GridData( GridData.FILL_HORIZONTAL);
		reportsButton.setLayoutData( gridData );
		reportsButton.setText("Reports...");
		reportsButton.setEnabled(true);

		adminButton = new Button( main, SWT.PUSH);
		gridData = new GridData( GridData.FILL_HORIZONTAL);
		adminButton.setLayoutData( gridData );
		adminButton.setText("Admin...");
		adminButton.setEnabled(true);

		return main;
	}
	
	public NewEntryWindow openNewEntryWindow() {
		SWTNewEntryWindow newEntryWindow = new SWTNewEntryWindow();
		newEntryWindow.openNewEntryWindow(sShell);

		return newEntryWindow;
	}

	public void setCreateNewButtonAction(final Runnable action) {
		signInButton.addListener(SWT.Selection, new Listener() {
		
			public void handleEvent(Event event) {
				action.run();
		
			}
		});
	}

	public void setOpenReportsButtonAction(final Runnable action) {
		reportsButton.addListener(SWT.Selection, new Listener() {
		
			public void handleEvent(Event event) {
				action.run();
		
			}
		});
	}

	public void initialFillTableEntries(int count, List<LogBookEntry> logBookEntries) {
		currentEntriesTable.clearAll();
		currentEntriesTable.setItemCount(count);

		for (int i=0; i < logBookEntries.size(); i++)
		{
			LogBookEntry entry = logBookEntries.get(i);
			createTableEntry(entry, i);
		}
	}


	private void createTableEntry(LogBookEntry entry, int index) {
		TableItem item = currentEntriesTable.getItem(index);
		populateTableItem(entry, item);
	}

	private void populateTableItem(LogBookEntry entry, TableItem item) {
		String[] fields =  {
				FormatUtil.formatDate( entry.getEntryOpenDate() ),
				FormatUtil.formatDate( entry.getEntryCloseDate() ),
				formatRowers(entry.getRowers()),
				formatLevels(entry.getRowers()),
				entry.getBoat().getName(),
				formatDistance( entry.getDistanceRowed()),
				entry.getComment()
		};
		if (entry.getEntryCloseDate() == null)
		{
			FontData[] fontData = item.getFont().getFontData();
			for (FontData fd : fontData)
			{
				fd.setStyle(SWT.BOLD);
			}
			item.setFont(new Font(display, fontData));
		}
		item.setText(fields);
	}

	private String formatRowers(List<Rower> rowers) {
		StringBuilder b = new StringBuilder();
		for (int i = 0; i < rowers.size(); i++)
		{
			if (i>0)
				b.append("/");
			b.append( rowers.get(i).getName());
		}
		return b.toString();
	}

	private String formatLevels(List<Rower> rowers) {
		StringBuilder b = new StringBuilder();
		for (int i = 0; i < rowers.size(); i++)
		{
			if (i>0)
				b.append("/");
			b.append( rowers.get(i).getLevel());
		}
		return b.toString();
	}

	private String formatDistance(Double distanceRowed) {
		if (distanceRowed == null)
			return "";
		return FormatUtil.formatMiles(distanceRowed);
	}

	public void addAdditionalEntries(int index, List<LogBookEntry> result) {
		for (int i=0; i< result.size(); i++)
		{
			TableItem item = currentEntriesTable.getItem(i+index);
			populateTableItem(result.get(i), item);
		}
	}
	
	public void showError(Exception e) {
		e.printStackTrace();
		MessageBox errorDialog = new MessageBox(sShell, SWT.ICON_ERROR | SWT.OK);
		errorDialog.setText("An error occurred...");
		errorDialog.setMessage(e.getMessage());
		errorDialog.open();
	}

	public void setSignOutButtonAction(final Runnable runnable) {
		signOutButton.addListener(SWT.Selection, new Listener() {
		
			public void handleEvent(Event event) {
				runnable.run();
			}
		
		});
	}

	public void setNewDamageButtonAction(final Runnable action) {
		reportDamageButton.addListener(SWT.Selection, new Listener() {
		
			public void handleEvent(Event event) {
				action.run();
			}
		});
	}

	public void setTableScrollDownListener(Listener listener) {
		currentEntriesTable.addListener(SWT.SetData, listener);
	}

	public void setAdminButtonAction(final Runnable with) {
		adminButton.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event arg0) {
				with.run();
			}
		});
	}

	public ReportNewDamageWindow openReportNewDamageWindow() {
		SWTReportNewDamageWindow window = new SWTReportNewDamageWindow();
		window.openReportNewDamageWindow(sShell);
		return window;
	}

	public SignOutWindow openSignOutWindow() {
		SWTSignOutWindow signOutWindow = new SWTSignOutWindow();
		signOutWindow.openSignOutWindow(sShell);
		return signOutWindow;
	}

	public ReportsWindow createReportsWindow()
	{
		return new SWTReportsWindow(sShell);
	}

	public AdminWindow createAdminWindow() {
		SWTAdminWindow window = new SWTAdminWindow(sShell);
		return window;
	}

}
